﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using VietThinks.Model;
using VietThinks.Contract;

namespace VietThinks.Service
{
    internal class DtoRepository<TDto, TEntity> : IDisposable
        where TDto : IdentifiableDto
        where TEntity : DomainEntity
    {
        protected DtoRepository(DomainRepository repository)
        {
            this.repository = repository;
        }

        public static DtoRepository<TDto, TEntity> Open()
        {
            var repository = DomainRepository.Open();

            return new DtoRepository<TDto, TEntity>(repository);
        }

        #region IDisposable Members

        private bool disposed = false;

        public void Dispose()
        {
            if (!this.disposed)
            {
                this.repository.Dispose();

                this.disposed = true;
            }
        }

        #endregion

        protected readonly DomainRepository repository;

        internal DomainRepository DomainRepository { get { return this.repository; } }

        protected virtual TEntity ToEntity(TDto dto)
        {
            return Convert.Dto(dto).ToEntity<TEntity>(this.DomainRepository);
        }

        protected virtual TDto ToDto(TEntity entity)
        {
            return Convert.Entity(entity).ToDto<TDto>();
        }

        public virtual TDto Get(object id)
        {
            var entity = this.repository.Get<TEntity>(id);

            return this.ToDto(entity);
        }

        public virtual TDto GetOne(Expression<Func<TEntity, bool>> filter)
        {
            var entity = this.repository.Query<TEntity>().Where(filter).FirstOrDefault();

            if (entity == null)
            {
                return null;
            }

            return Convert.Entity(entity).ToDto<TDto>();
        }

        public virtual IList<TDto> Get(Expression<Func<TEntity, bool>> filter)
        {
            return this.repository.Get(filter).ToList().Select(e => this.ToDto(e)).ToList();
        }

        public virtual IList<TDto> GetAll()
        {
            return this.repository.Query<TEntity>().ToList().Select(e => this.ToDto(e)).ToList();
        }

        public virtual object Add(TDto dto)
        {
            var entity = this.ToEntity(dto);

            return this.repository.Add(entity);
        }

        public virtual void Update(TDto dto)
        {
            var entity = this.ToEntity(dto);

            this.repository.Update(entity);
        }

        public virtual void AddOrUpdate(TDto dto)
        {
            var entity = this.ToEntity(dto);

            this.repository.AddOrUpdate(entity);
        }

        public virtual void Remove(TDto dto)
        {
            var entity = this.ToEntity(dto);

            this.repository.Remove(entity);
        }
    }
}
